home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / newsgrp / group94c.txt / 000046_kwalker@sirtur.premenos.com _Thu Dec 29 08:56:04 1994.msg < prev    next >
Internet Message Format  |  1995-02-09  |  6KB

  1. Received: from optima.CS.Arizona.EDU by cheltenham.CS.Arizona.EDU; Thu, 29 Dec 1994 10:04:04 MST
  2. Received: from gatekeeper.premenos.com by optima.CS.Arizona.EDU (5.65c/15) via SMTP
  3.     id AA21891; Thu, 29 Dec 1994 10:03:57 MST
  4. Received: from localhost (smap@localhost) by gatekeeper.premenos.com (8.6.5/8.6.5) id JAA22460 for <icon-group@cs.arizona.edu>; Thu, 29 Dec 1994 09:03:51 -0800
  5. Received: from sirtur.premenos.com(150.105.100.47) by mail.premenos.com via smap (V1.3mjr)
  6.     id sma022458; Thu Dec 29 09:03:06 1994
  7. Received: by sirtur.sirtur.premenos.com (5.x/SMI-SVR4)
  8.     id AA05637; Thu, 29 Dec 1994 08:56:04 -0800
  9. Date: Thu, 29 Dec 1994 08:56:04 -0800
  10. From: kwalker@sirtur.premenos.com (Ken Walker)
  11. Message-Id: <9412291656.AA05637@sirtur.sirtur.premenos.com>
  12. To: icon-group@cs.arizona.edu
  13. Subject: Re: Truth Tables...
  14. X-Sun-Charset: US-ASCII
  15.  
  16. I've been writing too much C and not enough Icon lately, so I decided it
  17. was time to have some fun. Below is a different variation on the theme
  18. of truth table generators.
  19.  
  20. Ken Walker, kwalker@premenos.com
  21. Premenos Coporation, Concord, Ca. 94520
  22.  
  23. -------------------------------- Cut Here -----------------------------
  24. #
  25. # This program takes as input on the command line a logical formula
  26. # containing variables and produces a truth table for the formula.
  27. # See below for the formula grammar.
  28. #
  29. # Ken Walker 12/29/94
  30.  
  31. #
  32. # The following records are nodes in the syntax tree of a formula.
  33. #
  34. record True()
  35. record False()
  36. record Not(a)
  37. record And(a,b)
  38. record Or(a,b)
  39. record Xor(a,b)
  40.  
  41. global vars, var_set
  42.  
  43. procedure main(a)
  44.     local formula, parsed, symtab, max_var_len, formula_len
  45.  
  46.     #
  47.     # parse the formula, putting the variables in the 'vars' list.
  48.     #
  49.     vars := []
  50.     var_set := set()
  51.     formula := a[1] | stop("please give a formula on the command line")
  52.     formula ? {
  53.     parsed := expr()
  54.         pos(0) | stop("invalid formula")
  55.     }
  56.  
  57.     #
  58.     # compute some lengths for formating output
  59.     #
  60.     formula_len := 5
  61.     formula_len <:= *formula
  62.     max_var_len := 6
  63.     every max_var_len <:= *!vars
  64.  
  65.     #
  66.     # output header line with variable names and formula
  67.     #
  68.     write()
  69.     every writes(center(!vars, max_var_len + 1))
  70.     writes(" | ")
  71.     write(center(formula, formula_len))
  72.     write(repl("-", *vars * (max_var_len + 1) + 3 + formula_len))
  73.  
  74.     #
  75.     # compute and print each set of variable assignments and formula
  76.     # results
  77.     #
  78.     symtab := table()
  79.     every assign_bool(vars, symtab) do {
  80.     every writes(center(type(symtab[!vars]), max_var_len + 1))
  81.         writes(" | ")
  82.         write(center(type(eval(parsed, symtab)), formula_len))
  83.     }
  84. end
  85.  
  86. #
  87. # For each variable in a list, assign boolean values in a symbol
  88. # table. Boolean values are represented by True and False records.
  89. # This is a recursive generator producing all combinations of
  90. # assignments.
  91. #
  92. procedure assign_bool(vars, symtab)
  93.     local var   
  94.  
  95.     if *vars == 0 then
  96.         return  # all variables are assigned
  97.  
  98.     var := vars[1]     # variable this call assigns to
  99.     vars := vars[2:0]  # rest of variables
  100.  
  101.     symtab[var] := True()
  102.     suspend assign_bool(vars, symtab)
  103.     symtab[var] := False()
  104.     suspend assign_bool(vars, symtab)
  105. end
  106.  
  107. #
  108. # Evaluate the parsed formual, using the boolean assignments to variables
  109. # in symtab. Return a True record or a False record.
  110. #
  111. procedure eval(parsed, symtab)
  112.     case type (parsed) of {
  113.         "string":
  114.             return symtab[parsed]
  115.         "True" | "False":
  116.             return parsed
  117.         "Not":
  118.              if type(eval(parsed.a, symtab)) == "True" then
  119.                  return False()
  120.              else
  121.                  return True()
  122.         "And":
  123.              if type(eval(parsed.a, symtab)) == "True" &
  124.                 type(eval(parsed.b, symtab)) == "True" then
  125.                  return True()
  126.              else
  127.                  return False()
  128.         "Or":
  129.              if type(eval(parsed.a, symtab)) == "True" |
  130.                  type(eval(parsed.b, symtab)) == "True" then
  131.                  return True()
  132.              else
  133.                  return False()
  134.         "Xor":
  135.              if type(eval(parsed.a, symtab)) ~==
  136.                  type(eval(parsed.b, symtab)) then
  137.                  return True()
  138.              else
  139.                  return False()
  140.  
  141.    }
  142. end
  143.  
  144. #
  145. # primative parser for grammar:
  146. #
  147. #    <expr> ::=  <term> |
  148. #                <expr> and <term> |
  149. #                <expr> or <term> |
  150. #                <expr> xor <term> |
  151. #
  152. #    <term> ::= true |
  153. #               false |
  154. #               <ident> |
  155. #               <not> <term> |
  156. #               ( <expr> )
  157. #
  158. procedure expr()
  159.     local e
  160.  
  161.     e := term()
  162.     repeat {
  163.         skip_whsp()
  164.     if ="and" then {
  165.            e := And(e, term())
  166.         }
  167.     else if ="or" then {
  168.            e := Or(e, term())
  169.         }
  170.     else if ="xor" then {
  171.            e := Xor(e, term())
  172.         }
  173.         else
  174.             return e
  175.     }
  176. end
  177.  
  178. procedure term()
  179.     local t
  180.     static ident_chars
  181.  
  182.     initial ident_chars := &letters ++ &digits ++ '_'
  183.  
  184.     skip_whsp()
  185.     if ="(" then {
  186.     t := expr()
  187.         skip_whsp()
  188.     if not =")" then
  189.        stop("missing ')'")
  190.     return t
  191.     }
  192.     else if ="not" then
  193.        return Not(term())
  194.     else if ="true" then
  195.        return True()
  196.     else if ="false" then
  197.        return False()
  198.     else if t := tab(many(ident_chars)) then {
  199.     if not member(var_set, t) then {
  200.          insert(var_set, t)
  201.              put(vars, t)
  202.         }
  203.     return t
  204.     }
  205.     else
  206.     stop("invalid formula")
  207. end
  208.  
  209. procedure skip_whsp()
  210.    static white_sp
  211.  
  212.    initial white_sp := ' \t'
  213.  
  214.    tab(many(white_sp))
  215. end